<?php
/**
 * Filters modify the AMF message has a whole, actions modify the AMF message PER BODY
 * This allows batching of calls
 * 
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @copyright (c) 2003 amfphp.org
 * @package flashservices
 * @subpackage filters
 * @version $Id: Filters.php 90 2011-01-16 09:23:26Z nicolas.surian $
 */

/**
 * required files
 */ 
require_once(AMFPHP_BASE . 'amf/util/TraceHeader.php');

/**
 * DeserializationFilter has the job of taking the raw input stream and converting in into valid php objects.
 * 
 * The DeserializationFilter is just part of a set of Filter chains used to manipulate the raw data.  Here we
 * get the input stream and convert it to php objects using the helper class AMFInputStream.
 */
function deserializationFilter(&$amf) {
    if($GLOBALS['amfphp']['native'] === true && function_exists('amf_decode'))
    {
        include_once(AMFPHP_BASE . "amf/io/AMFBaseDeserializer.php");
        include_once(AMFPHP_BASE . "amf/io/AMFBaseSerializer.php");
        $deserializer = new AMFBaseDeserializer($amf->rawData); // deserialize the data
    }
    else
    {
        include_once(AMFPHP_BASE . "amf/io/AMFDeserializer.php");
        include_once(AMFPHP_BASE . "amf/io/AMFSerializer.php");
        $deserializer = new AMFDeserializer($amf->rawData); // deserialize the data
    }
    
    $deserializer->deserialize($amf); // run the deserializer
    
    //Add some headers
    $headers = $amf->_headerTable;
    if(isset($headers) && is_array($headers))
    {
        foreach($headers as $key => $value)
        {
            Headers::setHeader($value->name, $value->value);
        }
    }
    
    //Set as a describe service
    $describeHeader = $amf->getHeader(AMFPHP_SERVICE_BROWSER_HEADER);
   
    if ($describeHeader !== false) {
        if($GLOBALS['amfphp']['disableDescribeService'])
        {
            //Exit 
            trigger_error("Service description not allowed", E_USER_ERROR);
            die();
        }
        $bodyCopy = &$amf->getBodyAt(0);
        $bodyCopy->setSpecialHandling('describeService');
        $bodyCopy->noExec = true;
    }
}

/**
 * AuthenticationFilter looks at the credential headers, starts sessions, etc.
 */
function authenticationFilter (&$amf) {
    $authHeader = $amf->getHeader(AMFPHP_CREDENTIALS_HEADER);

    if ($authHeader !== false && $authHeader->value !== AMFPHP_CLEARED_CREDENTIALS) {
        //In PHP5, objects are always pass-by-ref, hence this branch
        if(AMFPHP_PHP5)
        {
            $bodyCopy = clone($amf->getBodyAt(0));
        }
        else
        {
            $bodyCopy = $amf->getBodyAt(0);
        }
        
        $uri = $bodyCopy->targetURI;
        $lpos = strrpos($uri, ".");
        $cp = substr($uri, 0, $lpos + 1) . "_authenticate";
        $bodyCopy->targetURI = $cp;
        $bodyCopy->setSpecialHandling('auth');
        $val = $authHeader->value;
        $bodyCopy->setValue($val);
        $amf->addBodyAt(0, $bodyCopy);
        
        //Make it so that the data will stop being transmitted
        $clearHeader = array('name' => 'Credentials', 'mustUnderstand' => false, 
            'data' => AMFPHP_CLEARED_CREDENTIALS);
        $outHeader = new MessageHeader("RequestPersistentHeader", true, $clearHeader);
        $amf->addOutgoingHeader($outHeader);
    }

    $sessionName = session_name();
    if($sessionName == "" || $sessionName == NULL)
    {
        //Fix for godaddy not allowing ini_get
        $sessionName = "PHPSESSID";
    }
    session_start();
    $session_id = session_id();
    if(!strpos($_SERVER['QUERY_STRING'], $session_id) !== FALSE)
    {
        /**
         Instead of trying to guess if using https, 
         just use AppendTogGatewayUrl instead
         of ReplaceGatewayUrl
        */
        if(strrpos($_SERVER['QUERY_STRING'], "?") !== FALSE)
        {
            $joint = "&";
        }
        else
        {
            $joint = "?";
        }
        $outHeader = new MessageHeader("AppendToGatewayUrl", false, $joint . $sessionName . "=" . $session_id);
        $amf->addOutgoingHeader($outHeader);
    }
}

/**
 * Executes each of the bodys
 */
function batchProcessFilter(&$amf)
{
    $bodycount = $amf->numBody();
    
    for ($i = 0; $i < $bodycount; $i++) {
        $bodyObj = &$amf->getBodyAt($i);
        $actions = $GLOBALS['amfphp']['actions'];
        foreach($actions as $key => $action)
        {
            $results = $action($bodyObj);
            if($results === false)
            {
                break;
            }
        }
    }
    
    $bodycount = $amf->numBody();
    
    for ($i = 0; $i < $bodycount; $i++) {
        $bodyObj = &$amf->getBodyAt($i);
        if($bodyObj->getSpecialHandling() == 'auth' && $bodyObj->getResults() === NULL)
        {
            $amf->removeBodyAt($i);
            break;
        }
    }
}

/**
 * Adds debugging information to outgoing packet
 */
function debugFilter (&$amf) {
    //Add trace headers before outputting
    if(!$GLOBALS['amfphp']['isFlashComm'] && !$GLOBALS['amfphp']['disableTrace'])
    {
        $headerresults = array(); // create a result array
        $headerresults[0] = array(); // create a sub array in results (CF seems to do this, don't know why)
        
        if(count(NetDebug::getTraceStack()) != 0)
        {
            $ts = NetDebug::getTraceStack();    
            $headerresults[0][] = new TraceHeader($ts);
        }
        if(Headers::getHeader("serviceBrowser") == true)
        {
            global $amfphp;
            $amfphp['totalTime'] = microtime_float() - $amfphp['startTime'];
            $headerresults[0][] = new ProfilingHeader();
        }
        
        //Get the last body in the stack
        if(count($headerresults[0]) > 0)
        {
            $body = &$amf->getBodyAt($amf->numBody() - 1);
            
            $headers = new MessageBody(NULL, $body->responseIndex, NULL); // create a new amf body
            $headers->responseURI = $body->responseIndex . "/onDebugEvents"; // set the response uri of this body
            
            $headers->setResults($headerresults); // set the results.
            $amf->addBodyAt(0, $headers);
        }
    }
}

/**
 * Serializes the object
 */
function serializationFilter (&$amf) {
    if($GLOBALS['amfphp']['native'] === true && function_exists('amf_decode'))
    {
        $serializer = new AMFBaseSerializer(); // Create a serailizer around the output stream
    }
    else
    {
        $serializer = new AMFSerializer(); // Create a serailizer around the output stream
    }
    $result = $serializer->serialize($amf); // serialize the data
    $amf->outputStream = $result;
}
?>